#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "func.h"

static int Node_num=0;

int Get_Node_Num()
{
    return Node_num;
}

void Set_Node_Num(int num)
{
    Node_num = num;
}

// 有空节点的链表
// 头节点不存放数据
pLink_List_t Double_Cycle_Link_List_Init()
{
    pLink_List_t phead = ( pLink_List_t )malloc( sizeof( Link_List_t ));
    if ( phead == NULL )
    {
        perror("Init Double_Cycle_Link_List fail");
        return phead;
    }
    memset( phead, 0, sizeof(Link_List_t));
    phead->prev = phead;
    phead->next = phead;
    return phead;
}



pLink_List_t Create_new_node(pLink_List_t phead, char title[],int page,char color[])
{
    pLink_List_t pnew = (pLink_List_t)malloc(sizeof(Link_List_t));
    if (pnew == NULL)
    {
        perror("malloc a new node fail");
        return NULL;
    }
    Set_Node_Num(Get_Node_Num()+1);
    pnew->prev = NULL;
    strcpy(pnew->color,color);
    pnew->page = page;
    strcpy(pnew->title,title);
    pnew->next = NULL;
    return pnew;    
}

pLink_List_t Create_new_node_scanf(pLink_List_t phead)
{
    pLink_List_t pnew = (pLink_List_t)malloc(sizeof(Link_List_t));
    if (pnew == NULL)
    {
        perror("malloc a new node fail");
        return NULL;
    }
    char color[10];
    int page;
    char title[20];
    printf("请输入书名:");
    scanf("%s",title);
    while(getchar()!='\n');
    printf("请输入页数:");
    scanf("%d",&page);
    while(getchar()!='\n');
    printf("请输入颜色:");
    scanf("%s",color);
    while(getchar()!='\n');

    Set_Node_Num(Get_Node_Num()+1);
    pnew->prev = NULL;
    strcpy(pnew->color,color);
    pnew->page = page;
    strcpy(pnew->title,title);
    pnew->next = NULL;
    return pnew;    
}


//头插
void Double_Cycle_Link_List_Head_Insert(pLink_List_t phead, pLink_List_t node)
{
    pLink_List_t plink = phead;
    if (node == NULL)
    {
        perror("Head insert a node fail");
        return;
    }
    // 判断是否有首节点
    if (phead->next == phead&&phead->prev==phead)
    {
        plink->prev = node;
        plink->next = node;
        node->prev = phead;
        node->next = phead;
        return;
    }
    // 头插
    //我的头结点的pre不需要动，next需要动
    //插入的node节点prev和next都需要动
    //前节点的prev需要移动到插入的节点上   
    node->next = phead->next;
    node->prev = phead;
    phead->next->prev=node;
    phead->next = node;
    
}

//查找功能
void Double_Cycle_Link_List_Search(pLink_List_t phead)
{
    if (phead->next == phead)
    {
        printf("书架中没有书本");
        return;
    }
    char name[20];
    printf("请输入要查找的书名:");
    scanf("%s",name);
    while(getchar()!='\n');
    pLink_List_t plink = phead->next;

    while (plink != phead)
    {
        if (strcmp(plink->title,name)==0)
        {
            printf("书名:%s,页数:%d,颜色:%s\n",plink->title,plink->page,plink->color);
            return ;
        }
        plink = plink->next;
    }

    if (plink == phead)
    {
        printf("书架中没有此书");
        return;
    }
}

//删除功能
void Double_Cycle_Link_List_Random_Delet(pLink_List_t phead)
{
    pLink_List_t plink=phead;
    pLink_List_t ptemp=NULL;

    char name[20];
    printf("请输入要删除的书名:");
    scanf("%s",name);
    while(getchar()!='\n');
    
    //plink指向需要删除节点的前一个节点
    while(strcmp(plink->next->title,name)!=0)
    {
        if(plink->next==phead)
        {
            printf("链表中无此数据\n");
            return;
        }

        plink=plink->next;
    }
    //ptemp保存要删除的节点的指针 
    ptemp=plink->next;
    ptemp->next->prev=plink;
    plink->next=ptemp->next;
    free(ptemp);
    printf("\t\t删除成功\n");
    Node_num--;
    ptemp=NULL;
}

//修改功能
// 修改数据
void Double_Cycle_Link_List_Modify(pLink_List_t phead)
{
    char name[20],modifide_name[20],color[10];
    int page,choice;
    if (phead->next == phead)
    {
        printf("书架没有书可以修改");
        return;
    }

    printf("请输入要修改的书的名字:");
    scanf("%s",name);
    while(getchar()!='\n');
 
    pLink_List_t plink = phead->next;

    while (plink != phead)
    {
        if (strcmp(plink->title,name)==0)
        {
            printf("选择需要修改的信息:1.书名  2.页数  3.颜色  4.放弃修改\n");
            scanf("%d",&choice);

            while(choice!=4)
            {
                switch(choice)
                {
                    case 1:
                        printf("请输入新的书本名字:");
                        scanf("%s",modifide_name);
                        while(getchar()!='\n');
                        strcpy(plink->title,modifide_name);
                        break;
                    case 2:
                        printf("请输入新的书本页数");
                        scanf("%d",&page);
                        plink->page=page;
                        break;
                    case 3:
                        printf("请输入新的书本颜色:");
                        scanf("%s",color);
                        while(getchar()!='\n');
                        strcpy(plink->color,color);
                        break;
                    case 4:
                        return;
                        break;
                    default:
                        printf("输入错误，重新输入\n");
                        break;
                }
                printf("选择需要修改的信息:1.书名  2.页数  3.颜色  4.放弃修改\n");
                scanf("%d",&choice);
            }
            return;
        }
        plink = plink->next;
    }

    if (plink == phead)
    {
        printf("链表中找不到此数据\n");
        return;
    }
}


//遍历链表
void Print_Link_List_next(pLink_List_t phead)
{
    pLink_List_t plink = phead->next;

    if (plink == phead)
    {
        perror("None Link List");
        return;
    }

    while (plink != phead)
    {
        printf("书名:%s,页数:%d,颜色:%s\n",plink->title,plink->page,plink->color);
        plink = plink->next;
    }
    printf("\n");
}

//排序功能
void Double_Cycle_Link_list_Sort(pLink_List_t phead)
{
    if( Get_Node_Num() <= 1 )
    {
        printf("无足够可以排序");
        return;
    }

    for(int i=0;i< Get_Node_Num()-1;i++)
    {  
        pLink_List_t plink=phead->next;
        pLink_List_t ptemp=plink->next; 
        for(int k=0;k <  Get_Node_Num()-1-i;k++)
        {  
            if( (plink->page) < (ptemp->page) )
            {
                 //更新外围节点
                //前外围节点指向交换后的节点
                //后外围节点指向交换后的节点
                plink->prev->next = ptemp;
                ptemp->next->prev = plink;
                
                // 保存临时指针
                pLink_List_t temp_next = ptemp->next;
                
                // 处理两个交换的节点的next指针域（修改后的两行）
                plink->next = temp_next;
                ptemp->next = plink;

                // 处理两个交换节点的prev指针域（修改后的两行）
                ptemp->prev = plink->prev;
                plink->prev = ptemp;

                //成功交换了的话，第二个节点其实就成为了第一个节点了
                plink = ptemp->next;
                ptemp = plink->next;
            }    
            else{
                plink=plink->next;
                ptemp=plink->next;
            }
            
        }

    }
    Print_Link_List_next(phead);
}

//释放链表
void Release_Cycle_Link_list(pLink_List_t phead)
{
    pLink_List_t plink = phead->next;
    pLink_List_t ptemp = NULL;

    //不只有头结点的情况
    while (plink != phead)
    {
        ptemp = plink->next;
        free(plink);
       Set_Node_Num(Get_Node_Num()-1);
        plink = ptemp;
    }
    free(phead);
    
    printf("链表已经全部释放\n");
}


//翻书功能，通过输入命令，输出上一本或下一本书本信息
void Flip_book(pLink_List_t phead)
{
    if(Get_Node_Num()<=1)
    {
        if(Get_Node_Num()==0)
        {
            printf("书库中没有书");
            return ;
        }
        else 
        {
            printf("书库中只有一本书，无法翻书");
            return;
         }
    }

    //指向第一本书
    pLink_List_t plink=phead->next;
    char cmd[20] ;
    memset(cmd,0,20);

    printf("请键盘输入命令：prev.上一本 next.下一本 quit.退出\n");
    scanf("%s",cmd);
    while( getchar()!='\n');

    while(1)
    {    
        if(strcmp(cmd,"prev")==0)
        {
            plink=plink->prev;
            //如果指向头结点，就指向最后一本
            if(plink==phead)
            {
                plink=phead->prev;
            }

            printf("书名:%s,页数:%d,颜色:%s\n",plink->title,plink->page,plink->color);
        }
        else if(strcmp(cmd,"next")==0)
        {
            plink=plink->next;
            //如果指向头结点，就指向最后一本
            if(plink==phead)
            {
                plink=phead->next;
            }
            printf("书名:%s,页数:%d,颜色:%s\n",plink->title,plink->page,plink->color);
        }
        else if(strcmp(cmd,"quit")==0)
        {
            break;
        }
        else
        {
            printf("输入错误,请重新输入\n");
        }

    

        printf("请键盘输入命令：prev.上一本 next.下一本 quit.退出\n");
        scanf("%s",cmd);
        while( getchar()!='\n');
    }



}


//菜单功能
void Menu()
{
    
    printf("\t\t\t请选择想要的功能");
    printf("\n1.查看书架");
    printf("\n2.添加图书");
    printf("\n3.查找图书");
    printf("\n4.删除图书");
    printf("\n5.修改图书信息");
    printf("\n6.翻页");
    printf("\n7.按照页数排序");
    printf("\n8.退出");
    printf("\n请输入您的选择：");
    printf("\n");

}

